package com.helloniu.controller {

import com.helloniu.fl.NCHandler;
import com.helloniu.fl.NSHandler;
import com.helloniu.fl.SOHandler;
import com.helloniu.fl.util.Tool;
import com.helloniu.model.UserListModel;
import com.helloniu.red5.info.BussinessUnit;
import com.helloniu.red5.info.UserInfo;

import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
import flash.net.Responder;
import flash.utils.ByteArray;

public class UserListController extends AbsController {
    public function UserListController() {
        super();

        model = new UserListModel();
    }

    public static function getIns():UserListController {
        if(controller == null) {
            controller = new UserListController();
        }

        return controller;
    }

    override public function initConnection(ancHandler:NCHandler, asoHandler:SOHandler, auserID:String):void {
        if(inited) {
            return;
        }

        inited = true;
        super.initConnection(ancHandler, asoHandler, auserID);
        this.soHandler.addChangeListener(statusChange);

        asoHandler.setProperty("SomeoneJoin", _userID); // notify server
        ncHandler.call("fl_ClientJoin", null, _userID); // notify all client

        var resp:Responder = new Responder(fl_getUserlistResultFunc);
        ncHandler.call("fl_getUserlist", resp);
    }

    // init the user list
    private function fl_getUserlistResultFunc(aa1:* = null, aa2:* =null):void {
        userList = new Array();

        for(var i:int = 0; i < aa1.length; i++) {
           var uinfo:UserInfo = new UserInfo();
           var barr:ByteArray = aa1[i] as ByteArray;

           try {
                 barr.position = 0;
                //Tool.traceT("==result=1=:"+barr.readUTF());
                  uinfo.parseData(barr);
           }
           catch(e:Error) {
               Tool.traceT("==error=:"+e);
           }

           userList.push(uinfo);
        }

        processUserListChange();
    }

    private function statusChange(asoHandler:SOHandler, pname:String = null,
        oldValue:* = null, newValue:* = null):void
    {
        if(pname == null) {
            return;
        }

        newValue = asoHandler.getProperty(pname);

        if(pname == "SomeoneJoin") {
            // do nothing
            if(newValue == _userID) {
            }
            else {
                if(userList == null) {
                    userList = new Array();
                }

                // add a user
                userList.push(new UserInfo(newValue + ""));
                processUserListChange();
            }
        }
        else if(pname == "SomeoneLeave") {
            processUserLeave(newValue);
        }
        else if(pname == "UpdateBussinessUnit") {
            var str:String = newValue + "";
            var arr:Array = str.split(":");
            updateUserInfo(arr[0], arr[1], arr[2] == "true");
        }
    }

    // remove a user
    private function processUserLeave(val:*):void {
        var leaveUser:String = val as String;
        var idx:int = -1;

        for(var i:int = 0; i < userList.length; i++) {
            var userObj:Object = userList[i];

            if(userObj.userID == leaveUser) {
                idx = i;
                break;
            }
        }

        userList = Tool.arrayRemove(userList, idx);
        processUserListChange();
    }

    private function processUserListChange():void {
        model.setUsers(userList);
        //userListDG.dataProvider = createDP();
        Tool.traceT("==userlistcontroller==: " + userList.length);
        updateViews();
    }

    // update userinfo
    private function updateUserInfo(uid:String, key:String, value:*):void {
        for(var i:int = 0; i < userList.length; i++) {
            var userObj:UserInfo = userList[i] as UserInfo;

            if(userObj.userID == uid) {
                if("video" == userObj.binfo.videoUnit.type) {
                    userObj.binfo.videoUnit.opened = value;
                }
                break;
            }
        }

        processUserListChange();
    }

    // open the camera
    public function openVideo(mic:Microphone = null, cam:Camera = null):void {
        if(publishStreamName == null) {
            publishStreamName = _userID + "VideoStream";
        }

        if(cam != null || mic != null) {
            publishHandler = new NSHandler(ncHandler.getNC());
            publishHandler.setStreamName(publishStreamName);
            publishHandler.setStartPublishFunc(startPublishFunc);
            publishHandler.publish(mic, cam);
        }
    }

    private function startPublishFunc(apublishnsHandler:NSHandler):void {
        Tool.traceT(apublishnsHandler.getStreamName() + ":publish OK");

        publishStreamChanged(true);
    }

    private function publishStreamChanged(published:Boolean):void {
        // @temp tonyy
        // update client
        // bytearray--base64--string
        soHandler.setProperty("UpdateBussinessUnit",
            _userID + ":" + "video" + ":" + published);

        updateBussinessUnit(published);

    }

    // update server side
    private function updateBussinessUnit(published:Boolean):void {
        var bunit:BussinessUnit = new BussinessUnit();
        bunit.type = "video";
        bunit.opened = published;

        var barr:ByteArray = new ByteArray();
        bunit.writeData(barr);

        ncHandler.call("fl_ClientUpdate", null, barr);
    }

    // close camera
    public function closeVideo():void {
        if(publishHandler != null) {
            publishHandler.closeStream();
        }

        publishStreamChanged(false);
    }

    public function createPlayVideo(uid:String):Video {
        var playHandler:NSHandler = new NSHandler(ncHandler.getNC());
        playVideos[uid] = playHandler;
        playHandler.setStreamName(uid + "VideoStream");
        playHandler.setStartPlayFunc(startPlayFunc);
        playHandler.play();

        var video:Video = new Video();
        video.attachNetStream(playHandler.getStream());

        return video;
    }

    private function startPlayFunc(aplayHandler:NSHandler):void {
       //Tool.traceT(aplayHandler.getStreamName() + ":play OK");
    }

    public function closePlayVideo(uid:String):void {
        try {
            playVideos[uid].closeStream();
        }
        catch(e:Error) {
            Tool.alert("close video error!");
        }

        playVideos[uid] = null;
    }

    private var playVideos:Object = new Object();
    private var userList:Array = new Array();
    private var views:Array = new Array();
    private var publishHandler:NSHandler = null;
    private var publishStreamName:String = null;
    private static var controller:UserListController;
}
}